﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading;
using Vkontakte.Api.Operations;

namespace Vkontakte.Api
{
	public sealed class ApiClient
		:IDisposable
	{
		private long _appid;
		private Session _session;
		private Thread _thread;
		private ManualResetEventSlim _event = new ManualResetEventSlim( false );
		private bool _sending = false;
		private Queue<BaseApiOperation> _operationQueue=new Queue<BaseApiOperation>();

		private Queue<BaseApiOperation> _highPriorityOperations=new Queue<BaseApiOperation>();

		public ApiClient(long appid,Session session)
		{
			_appid = appid;
			_session = session;
			_thread=new Thread( ThreadProc );
			_thread.Start();
		}

		~ApiClient()
		{
			if(_thread!=null)
			{
				_thread.Abort();
				_thread = null;
			}
		}


		public void Dispose()
		{
			if (_thread != null)
			{
				_thread.Abort();
				_thread = null;
			}
			GC.SuppressFinalize( this );
		}

		public void ExecuteHighPriorityQuerry(BaseApiOperation querry)
		{
			if (querry.CheckParams())
			{
				lock (_highPriorityOperations)
				{
					_highPriorityOperations.Enqueue(querry);
				}
			}
			else
			{
				throw new ArgumentException("Параметры API операции указаны не верно");
			}
		}

		public void ExecuteQuerry(BaseApiOperation querry)
		{
			if (querry.CheckParams())
			{
				lock (_operationQueue)
				{
					_operationQueue.Enqueue(querry);
				}
			}
			else
			{
				throw new ArgumentException("Параметры API операции указаны не верно");
			}
		}

		public long MyID
		{
			get
			{
				return _session != null ? _session.Mid : 0;
			}
		}


		private void ThreadProc()
		{
			try
			{
				do
				{
					BaseApiOperation querry;
					if (_highPriorityOperations.Count != 0)
					{
						lock (_highPriorityOperations)
						{
							querry = _highPriorityOperations.Dequeue();
						}
						querry.Start(_appid, _session.Mid, _session.Sid, _session.Secret);
						Thread.Sleep(400);
						continue;
					}


					if (_operationQueue.Count != 0)
					{
						lock (_operationQueue)
						{
							querry = _operationQueue.Dequeue();
						}
						querry.Start(_appid, _session.Mid, _session.Sid, _session.Secret);
						Thread.Sleep(400);
						continue;
					}

					
					Thread.Sleep(400);
				} while (true);
			}
			catch (ThreadAbortException tae)
			{

			}
		}


		public string GetVideoLocation(string name)
		{
			HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(string.Format("http://vkontakte.ru/{0}", name));
			webRequest.CookieContainer = _session.Cookies;
			var responce = webRequest.GetResponse();
			Stream s = responce.GetResponseStream();
			StreamReader r = new StreamReader(s);
			string page = r.ReadToEnd();
			int endParams = page.IndexOf("loadFlashPlayer");
			int startParams = page.IndexOf('(', endParams);
			endParams = page.IndexOf(')', startParams);
			string param = page.Substring(startParams + 1, endParams - startParams - 1);
			startParams = param.IndexOf('{');
			endParams = param.IndexOf('}', startParams);
			string param2 = param.Substring(startParams + 1, endParams - startParams - 1);
			string[] parts = param2.Split(',');
			string uid = "";
			string host = "";
			string vtag = "";
			string vkid = "";
			int hd = 0;
			for (int i = 0; i < parts.Length; i++)
			{
				if (parts[i].StartsWith("\"uid\""))
				{
					string[] test = parts[i].Split(':');
					uid = test[1].Trim('"');
					continue;
				}
				if (parts[i].StartsWith("\"host\""))
				{
					string[] test = parts[i].Split(new string[] { "\":\"" }, StringSplitOptions.RemoveEmptyEntries);
					host = test[1].Trim('"');
					host = host.Replace("\\/", "/");
					host = host.TrimEnd('/');
					if (host.StartsWith("http"))
					{
						host = host.Substring(7);
					}
					continue;
				}
				if (parts[i].StartsWith("\"vtag\""))
				{
					string[] test = parts[i].Split(':');
					vtag = test[1].Trim('"');
					continue;
				}

				if (parts[i].StartsWith("\"vkid\""))
				{
					string[] test = parts[i].Split(':');
					vkid = test[1].Trim('"');
					continue;
				}
				if (parts[i].StartsWith("\"hd\""))
				{
					string[] test = parts[i].Split(':');
					hd = int.Parse(test[1].Trim('"'));
				}
			}
			if (host.EndsWith("vkadre.ru"))
			{
				return string.Format("http://{0}/assets/videos/{1}{2}.vk.flv", host, vtag, vkid);
			}
			if (host.EndsWith("vkontakte.ru"))
			{
				switch (hd)
				{
					case 2:
						return string.Format("http://{0}/u{1}/video/{2}.240.mp4", host, uid, vtag);
					default:
						return string.Format("http://{0}/u{1}/video/{2}.flv", host, uid, vtag);
				}
				
			}

			return null;
		}
		

		public event Action OperationCompleted;
	}
}
